<?php


namespace app\api\controller;
use addons\third\model\Third;
use app\common\controller\Api;
use GuzzleHttp\Client as HttpClient;
use think\Cache;

class Login extends Api
{
    protected $appid;
    protected $appSecret;
    protected $getCodeUrl;
    protected $getTokenUrl;
    protected $getUserUrl;
    protected $redirectUrl;
    protected $noNeedLogin = ['getCode','loginRes', 'wechatJssdk'];
    protected $noNeedRight = ['*'];

    // 基本配置
    public function _initialize()
    {
        parent::_initialize();
        $config = get_addon_config('epay');
        $this->appid = $config['wechat']['app_id'];
        $this->appSecret = $config['wechat']['app_secret'];

        $this->getCodeUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect';
        $this->getTokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code';
        $this->getUserUrl = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN';
        $this->redirectUrl = urlencode($this->request->domain() . '/api/Login/loginRes');
    }

    /**
     * 网页授权获取code
     */
    public function getCode(){
        // TODO 前期测试用于清空值 session('wechat_user',NULL);
        if (!session('wechat_user')) {
            $url = sprintf($this->getCodeUrl, $this->appid, $this->redirectUrl);
            header("Location:" . $url);
        }else {
            $this->success('授权登录成功', session('wechat_user'));
        }
    }

    /**
     * 授权登录
     */
    public function loginRes()
    {
        $code = $this->request->post('code');  // 获取code

        if(!$code){
            $this->error(__('缺少参数code！'));
        }

        $getTokenUrl = sprintf($this->getTokenUrl, $this->appid, $this->appSecret, $code);

        // 获取access_token和openid
        $result = json_decode(file_get_contents($getTokenUrl),true);

        /* $result 输出结果
         * Array (
            [access_token]  => 44_ixUtEZiza2rDbtiP2JGJKwPdNi_VA6iODMCvvRIJ-k34TbU5XR04d74ekw37QfFthPzAS2bnPaycazBXl8AInQ
            [expires_in]    => 7200
            [refresh_token] => 44_LGyUp6YLNAdL2F8CppUXbjsxhnQpk1yvkAKZNnqSzDLN2itrfvPUY3mwFCsHHBbPF28GYyl1tMSxOuoj9sdQJg
            [openid]        => oaWII632e55s0ZuqCRQHsYQkMgFE
            [scope]         => snsapi_userinfo
        )*/

        if(!$result){
            $this->error('获取access_token和openid失败了');
        }

        // 分参
        extract($result);

        $access_token = $result['access_token'];
        $openid = $result['openid'];
        $getUserUrl = sprintf($this->getUserUrl, $access_token, $openid);

        // 获取用户信息
        $userInfo = json_decode(file_get_contents($getUserUrl),true);

        /* $userInfo 输出结果
         * Array (
            [openid] => oaWII632e55s0ZuqCRQHsYQkMgFE
            [nickname] => 霍文霆
            [sex] => 1
            [language] => zh_CN
            [city] =>
            [province] => 安徽
            [country] => 中国
            [headimgurl] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ/132
            [privilege] => Array ()
        )*/

        // 分参
        extract($userInfo);

        if (!empty($userInfo)) {

            $third = Third::get([ 'openid' => $openid]);
            if ($third) {
                $user = \app\common\model\User::get(['id' => $third->user_id]);
                if ($user->status != 'normal') {
                    $this->error(__('Account is locked'));
                }
                // 每次调用都会更新一次用户基本数据---例如用户修改头像和昵称，这样就会实时更新数据了
                $user->nickname = $userInfo['nickname'];
                $user->avatar = $userInfo['headimgurl'];
                $ret = $user->save();
                // 直接登陆
                $ret = $this->auth->direct($user->id);
            } else {


//                $ret = $this->auth->wxOfficialAccountsLogin($userInfo);
                $ret = $this->auth->register($userInfo['nickname'], 123456, '123@qq.com', 13385888888, []);
//                $ret = \app\common\model\User::create(['nickname' => $userInfo['nickname'], 'status' => 'normal']);
                $user = $this->auth->getUserinfo();
                $ret = Third::create(['user_id' => $user['id'], 'openid' => $openid, 'access_token' => $access_token], true);
            }
            if ($ret) {
//                $wechat_user = $this->auth->getUserInfo();
                // 把用户登录信息写入session中，这样就不需要每次都发起请求了
                session('wechat_user', $this->auth->getUserinfo());
                $this->success('授权登录成功', $this->auth->getUserinfo());
            } else {
                $this->error('授权登录失败了！');
            }
        }else{
            $this->error(__('获取用户信息失败了'));
        }
    }


    /**
     *
     * @author Tiger <1192851302@qq.com>
     * @return type
     */
    public function wechatJssdk() {
        $url = $this->request->post('url');  // 获取code
        $jsapi_ticket = $this->wechatJsapiTicket();
        if (empty($jsapi_ticket)) {
            return [];
        }
        $noncestr = $this->genRandom(16);
        $timestamp = time();
//        $url = request()->header('Referer', request()->domain() . '/home/index.html');
        $para = compact('jsapi_ticket', 'noncestr', 'timestamp', 'url');
        ksort($para);
        $string = $this->createLinkstring($para);
        $para['signature'] = sha1($string);
        $para['appid'] = $this->appid;

        $this->success('授权登录成功', $para);
    }

    public function createLinkstring($para) {
        $arg = "";
        foreach ($para as $key => $val) {
            $arg .= $key . "=" . $val . "&";
        }
        //去掉最后一个&字符
        $string = substr($arg, 0, -1);
        //如果存在转义字符，那么去掉转义
        //if (get_magic_quotes_gpc()) {
        //    $string = stripslashes($string);
        //}
        return $string;
    }

    /**
     *
     * @author Tiger <1192851302@qq.com>
     * @param type $size
     * @return string
     */
    public function genRandom($size) {
        $allLetterDigit = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
        $randomSb = "";
        $digitSize = count($allLetterDigit) - 1;
        for ($i = 0; $i < $size; $i++) {
            $randomSb .= $allLetterDigit[rand(0, $digitSize)];
        }
        return $randomSb;
    }

    /**
     *
     * @author Tiger <1192851302@qq.com>
     * @return type
     */
    public function wechatJsapiTicket() {
        $wechat_jsapi_ticket = Cache::get('wechat_jsapi_ticket');
        if ($wechat_jsapi_ticket) {
            return $wechat_jsapi_ticket;
        }
        $access_token = $this->wechatAccessToken();
        if (empty($access_token)) {
            return false;
        }
        $client = new HttpClient(['base_uri' => 'https://api.weixin.qq.com/']);
        $response = $client->request('GET', 'cgi-bin/ticket/getticket', ['query' => [
            'appid' => $this->appid,
            'secret' => $this->appSecret,
            'access_token' => $access_token,
            'type' => 'jsapi'
        ]]);
        $body = $response->getBody();
        $return = json_decode($body->getContents(), true);
        Cache::set('wechat_jsapi_ticket', $return['ticket'], 3600);
        return $return['ticket'];
    }

    /**
     *
     * @author Tiger <1192851302@qq.com>
     * @return type
     */
    public function wechatAccessToken() {
        $wechat_access_token = Cache::get('wechat_access_token');
        if ($wechat_access_token) {
            return $wechat_access_token;
        }
        $client = new HttpClient(['base_uri' => 'https://api.weixin.qq.com/']);
        $response = $client->request('GET', 'cgi-bin/token', ['query' => [
            'appid' => $this->appid,
            'secret' => $this->appSecret,
            'grant_type' => 'client_credential'
        ]]);
        $body = $response->getBody();
        $return = json_decode($body->getContents(), true);
        if (empty($return['access_token'])) {
            \think\facade\Log::debug('获取 access_token | ' . json_encode($return));
            return false;
        }
        Cache::set('wechat_access_token', $return['access_token'], 3600);
        return $return['access_token'];
    }

}
